const express = require('express');
const session = require('express-session');
const WidgetManager = require('./core/WidgetManager');
const I18nManager = require('./core/I18nManager');
const DatabaseManager = require('./core/DatabaseManager');
const AuthService = require('./core/AuthService');
const AuthMiddleware = require('./core/AuthMiddleware');
const path = require('path');

const app = express();
const port = process.env.PORT || 3000;

app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));

// Initialize services
const dbManager = new DatabaseManager();
const authService = new AuthService(dbManager);
const authMiddleware = new AuthMiddleware(authService);
const widgetManager = new WidgetManager(dbManager);
const i18nManager = new I18nManager();

// Session middleware
app.use(session({
    secret: 'your-secret-key-change-this-in-production',
    resave: false,
    saveUninitialized: false,
    cookie: {
        secure: false, // Set to true in production with HTTPS
        maxAge: 24 * 60 * 60 * 1000 // 24 hours
    },
    name: 'widget-platform-session'
}));

// Add cookie-parser middleware to read client-side cookies
const cookieParser = require('cookie-parser');
app.use(cookieParser());

// Initialize default admin user
authService.createDefaultAdmin();

// Authentication routes
app.post('/api/auth/login', async (req, res) => {
    try {
        const { username, password } = req.body;
        const result = await authService.login(username, password);
        
        console.log('Login - Session created:', result);
        
        // Set session cookie
        req.session.sessionId = result.sessionId;
        req.session.userId = result.user.id;
        
        // Set client-side cookie for persistence
        res.cookie('sessionId', result.sessionId, { 
            maxAge: 24 * 60 * 60 * 1000, // 24 hours
            httpOnly: false, // Allow client-side access
            path: '/'
        });
        
        res.json({
            success: true,
            user: result.user,
            sessionId: result.sessionId
        });
    } catch (error) {
        res.status(401).json({ error: error.message });
    }
});

app.post('/api/auth/logout', async (req, res) => {
    try {
        const sessionId = req.session.sessionId;
        if (sessionId) {
            await authService.logout(sessionId);
        }
        req.session.destroy();
        
        // Clear client-side cookie
        res.clearCookie('sessionId', { path: '/' });
        
        res.json({ success: true });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

app.get('/api/auth/me', authMiddleware.authenticate, (req, res) => {
    res.json({ user: req.user });
});

// User management routes (admin only)
app.get('/api/users', authMiddleware.requireAdmin, async (req, res) => {
    try {
        const users = await authService.getAllUsers();
        res.json(users);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

app.post('/api/users', authMiddleware.requireAdmin, async (req, res) => {
    try {
        const { username, password, role = 'user' } = req.body;
        const user = await authService.register(username, password, role);
        res.json({ success: true, user: user.toJSON() });
    } catch (error) {
        res.status(400).json({ error: error.message });
    }
});

app.put('/api/users/:userId/role', authMiddleware.requireAdmin, async (req, res) => {
    try {
        const { userId } = req.params;
        const { role } = req.body;
        await authService.updateUserRole(parseInt(userId), role);
        res.json({ success: true });
    } catch (error) {
        res.status(400).json({ error: error.message });
    }
});

app.delete('/api/users/:userId', authMiddleware.requireAdmin, async (req, res) => {
    try {
        const { userId } = req.params;
        await authService.deleteUser(parseInt(userId));
        res.json({ success: true });
    } catch (error) {
        res.status(400).json({ error: error.message });
    }
});

app.get('/api/widgets', (req, res) => {
  res.json(widgetManager.getAvailableWidgets());
});

// Get user's configured widgets from database
app.get('/api/widgets/user', authMiddleware.authenticate, async (req, res) => {
  try {
    const userWidgets = await dbManager.getWidgets(req.user.id);
    const widgetsWithData = userWidgets.map(widget => {
      const widgetInstance = widgetManager.getWidget(widget.id);
      return {
        id: widget.id,
        name: widget.name,
        config: widget.config,
        userId: widget.userId,
        createdAt: widget.createdAt,
        updatedAt: widget.updatedAt,
        data: widgetInstance ? widgetInstance.getData() : null
      };
    });
    res.json(widgetsWithData);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/widgets/:widgetName/instantiate', authMiddleware.authenticate, async (req, res) => {
  const { widgetName } = req.params;
  const { config } = req.body;
  
  try {
    const widget = await widgetManager.instantiateWidget(widgetName, config, req.user.id);
    res.json({
      id: widget.id,
      name: widget.getName(),
      config: widget.config
    });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

app.get('/api/widgets/:widgetId/data', authMiddleware.authenticate, (req, res) => {
  const { widgetId } = req.params;
  const widget = widgetManager.getWidget(widgetId);
  
  if (!widget) {
    return res.status(404).json({ error: 'Widget not found' });
  }
  
  // Check if widget belongs to current user
  if (widget.userId !== req.user.id) {
    return res.status(403).json({ error: 'Access denied' });
  }
  
  res.json(widget.getData());
});

app.post('/api/widgets/:widgetId/data', authMiddleware.authenticate, (req, res) => {
  const { widgetId } = req.params;
  const { data } = req.body;
  const widget = widgetManager.getWidget(widgetId);
  
  if (!widget) {
    return res.status(404).json({ error: 'Widget not found' });
  }
  
  // Check if widget belongs to current user
  if (widget.userId !== req.user.id) {
    return res.status(403).json({ error: 'Access denied' });
  }
  
  widget.updateData(data);
  res.json({ success: true });
});

app.delete('/api/widgets/:widgetId', authMiddleware.authenticate, async (req, res) => {
  const { widgetId } = req.params;
  const widget = widgetManager.getWidget(widgetId);
  
  if (!widget) {
    return res.status(404).json({ error: 'Widget not found' });
  }
  
  // Check if widget belongs to current user
  if (widget.userId !== req.user.id) {
    return res.status(403).json({ error: 'Access denied' });
  }
  
  try {
    await widgetManager.removeWidget(widgetId);
    res.json({ success: true });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// Language API
app.get('/api/languages', (req, res) => {
  res.json({
    current: i18nManager.getCurrentLanguage(),
    available: i18nManager.getAvailableLanguages()
  });
});

app.post('/api/language', (req, res) => {
  const { lang } = req.body;
  if (i18nManager.getAvailableLanguages().includes(lang)) {
    i18nManager.setLanguage(lang);
    res.json({ success: true, language: lang });
  } else {
    res.status(400).json({ error: 'Unsupported language' });
  }
});

// Widget template API for rendering
app.get('/api/widgets/:widgetId/template', authMiddleware.authenticate, (req, res) => {
  const { widgetId } = req.params;
  const widget = widgetManager.getWidget(widgetId);
  
  if (!widget) {
    return res.status(404).json({ error: 'Widget not found' });
  }
  
  // Check if widget belongs to current user
  if (widget.userId !== req.user.id) {
    return res.status(403).json({ error: 'Access denied' });
  }
  
  // Return widget-specific HTML template
  const template = widget.render();
  res.json({ template });
});

// Widget action API for component interactions
app.post('/api/widgets/:widgetId/actions/:action', authMiddleware.authenticate, async (req, res) => {
  const { widgetId, action } = req.params;
  const { data } = req.body;
  const widget = widgetManager.getWidget(widgetId);
  
  if (!widget) {
    return res.status(404).json({ error: 'Widget not found' });
  }
  
  // Check if widget belongs to current user
  if (widget.userId !== req.user.id) {
    return res.status(403).json({ error: 'Access denied' });
  }
  
  try {
    let result;
    
    // Handle legacy actions for backward compatibility
    switch (action) {
      case 'addTodo':
        result = await widget.addTodo(data.text, data.priority);
        break;
      case 'toggleTodo':
        result = await widget.toggleTodo(data.todoId);
        break;
      case 'deleteTodo':
        result = await widget.deleteTodo(data.todoId);
        break;
      case 'addEvent':
        result = await widget.addEvent(data.title, data.date, data.type, data.description);
        break;
      case 'deleteEvent':
        result = await widget.deleteEvent(data.eventId);
        break;
      case 'changeCalendarView':
        widget.changeView(data.direction);
        result = { success: true };
        break;
      case 'getStats':
        result = widget.updateStats();
        break;
      default:
        // Handle new widget-internal actions
        if (typeof widget[action] === 'function') {
          result = await widget[action](data);
        } else {
          return res.status(400).json({ error: 'Unknown action' });
        }
    }
    
    res.json({ success: true, result });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

app.listen(port, () => {
  console.log(`Widget platform running at http://localhost:${port}`);
});